# -*- coding: utf-8 -*-
"""
智慧职教MOOC视频下载器 - 视频下载模块
负责视频的下载、播放控制和文件管理
"""

import os
import re
import json
import time
import requests
from tqdm import tqdm
from selenium.webdriver.common.by import By
from config import HEADERS, COOKIES, MAX_DOWNLOAD_RETRIES, VIDEO_LOAD_TIMEOUT


class VideoDownloader:
    def __init__(self, driver):
        self.driver = driver
        
    def get_safe_filename(self, base_path, filename):
        """自动重命名，防止同名覆盖"""
        name, ext = os.path.splitext(filename)
        counter = 1
        new_filename = filename
        while os.path.exists(os.path.join(base_path, new_filename)):
            new_filename = f"{name}({counter}){ext}"
            counter += 1
        return new_filename

    def download_m3u8_video(self, m3u8_url, filename, headers=None, cookies=None):
        """下载m3u8格式视频，使用tqdm显示进度条"""
        if headers is None:
            headers = HEADERS
        if cookies is None:
            cookies = COOKIES
            
        try:
            resp = requests.get(m3u8_url, headers=headers, cookies=cookies, timeout=10)
            video_text = resp.text
            content_url = m3u8_url.rsplit('/', 1)[0] + '/'
            video_text = re.sub(r'#.*', '', video_text).split()
            os.makedirs(os.path.dirname(filename), exist_ok=True)
            
            # 过滤有效的ts片段
            valid_segments = [ts for ts in video_text if ts.strip()]
            total_segments = len(valid_segments)
            
            print(f"开始下载: {os.path.basename(filename)}")
            
            with open(filename, mode='ab') as f:
                # 使用tqdm显示进度条
                with tqdm(total=total_segments, desc="下载进度", unit="片段", 
                          bar_format="{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}]") as pbar:
                    for ts in valid_segments:
                        video_ts_url = content_url + ts
                        try:
                            video_data = requests.get(video_ts_url, headers=headers, cookies=cookies, timeout=10).content
                            f.write(video_data)
                            pbar.update(1)  # 更新进度条
                        except Exception as e:
                            tqdm.write(f"下载片段失败: {ts}, 错误: {e}")
            print(f"下载完成: {filename}")
            return True
            
        except Exception as e:
            print(f"下载m3u8视频失败: {e}")
            return False

    def download_mp4_video(self, mp4_url, filename, headers=None, cookies=None):
        """下载mp4格式视频"""
        if headers is None:
            headers = HEADERS
        if cookies is None:
            cookies = COOKIES
            
        try:
            with requests.get(mp4_url, headers=headers, cookies=cookies, stream=True) as r:
                r.raise_for_status()
                with open(filename, 'wb') as f:
                    for chunk in r.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)
            print(f"mp4下载完成: {filename}")
            return True
            
        except Exception as e:
            print(f"mp4下载失败: {e}")
            return False

    def try_play_video(self):
        """尝试播放视频"""
        try:
            # 等待页面加载
            time.sleep(3)
            
            # 1. ICVE 自定义播放器按钮
            button_selectors = [
                "#player_pause.screen-play-btn",
                "#player_pause_btn .screen-play-btn",
                ".screen-play-btn",
                "[id*='player'][id*='pause']"
            ]
            
            for selector in button_selectors:
                try:
                    buttons = self.driver.find_elements(By.CSS_SELECTOR, selector)
                    for btn in buttons:
                        if btn.is_displayed():
                            self.driver.execute_script("arguments[0].scrollIntoView(true);", btn)
                            time.sleep(0.5)
                            btn.click()
                            time.sleep(1)
                            self.driver.execute_script("arguments[0].click();", btn)
                            print(f"成功点击播放按钮: {selector}")
                            return True
                except Exception:
                    continue

            # 2. 原生video标签
            try:
                video_tags = self.driver.find_elements(By.TAG_NAME, "video")
                for video_tag in video_tags:
                    self.driver.execute_script("""
                        var video = arguments[0];
                        video.muted = true;
                        if (video.play) video.play();
                    """, video_tag)
                    time.sleep(1)
                    is_playing = self.driver.execute_script("return arguments[0] && !arguments[0].paused;", video_tag)
                    if is_playing:
                        print("成功播放video标签")
                        return True
            except Exception:
                pass

            # 3. 递归查找iframe
            iframes = self.driver.find_elements(By.TAG_NAME, "iframe")
            for iframe in iframes:
                try:
                    self.driver.switch_to.frame(iframe)
                    if self.try_play_video():
                        self.driver.switch_to.parent_frame()
                        return True
                    self.driver.switch_to.parent_frame()
                except Exception:
                    try:
                        self.driver.switch_to.parent_frame()
                    except Exception:
                        pass

            return False
            
        except Exception as e:
            print(f"播放视频异常: {e}")
            return False

    def get_video_source_from_page(self):
        """直接从页面元素中获取视频源"""
        try:
            # 方法1: 查找video标签的src属性
            video_elements = self.driver.find_elements(By.TAG_NAME, "video")
            for video in video_elements:
                src = video.get_attribute("src")
                if src and ('.mp4' in src or '.m3u8' in src):
                    if not any(filter_keyword in src for filter_keyword in ['webtrn.cn/page', 'heartBeat', 'sid=']):
                        print(f"从video标签获取到源: {src}")
                        return src
                
                # 检查source子元素
                sources = video.find_elements(By.TAG_NAME, "source")
                for source in sources:
                    src = source.get_attribute("src")
                    if src and ('.mp4' in src or '.m3u8' in src):
                        if not any(filter_keyword in src for filter_keyword in ['webtrn.cn/page', 'heartBeat', 'sid=']):
                            print(f"从source标签获取到源: {src}")
                            return src
            
            # 方法2: 执行JavaScript查找视频源
            try:
                video_src = self.driver.execute_script("""
                    var videos = document.getElementsByTagName('video');
                    for (var i = 0; i < videos.length; i++) {
                        var video = videos[i];
                        if (video.src && (video.src.includes('.mp4') || video.src.includes('.m3u8'))) {
                            if (!video.src.includes('webtrn.cn/page') && !video.src.includes('heartBeat')) {
                                return video.src;
                            }
                        }
                        // 检查currentSrc
                        if (video.currentSrc && (video.currentSrc.includes('.mp4') || video.currentSrc.includes('.m3u8'))) {
                            if (!video.currentSrc.includes('webtrn.cn/page') && !video.currentSrc.includes('heartBeat')) {
                                return video.currentSrc;
                            }
                        }
                    }
                    return null;
                """)
                
                if video_src:
                    print(f"通过JavaScript获取到视频源: {video_src}")
                    return video_src
                    
            except Exception as e:
                print(f"JavaScript获取视频源失败: {e}")
            
            # 方法3: 查找包含视频URL的所有元素
            try:
                all_elements = self.driver.find_elements(By.XPATH, "//*[contains(@src, '.mp4') or contains(@src, '.m3u8')]")
                for element in all_elements:
                    src = element.get_attribute("src")
                    if src and not any(filter_keyword in src for filter_keyword in ['webtrn.cn/page', 'heartBeat', 'sid=']):
                        print(f"从其他元素获取到源: {src}")
                        return src
            except Exception as e:
                print(f"查找其他元素失败: {e}")
            
            return None
            
        except Exception as e:
            print(f"获取页面视频源失败: {e}")
            return None

    def capture_video_links(self, max_attempts=5):
        """抓取视频链接"""
        m3u8_url = None
        mp4_url = None
        
        # 首先尝试从页面元素直接获取
        page_video_src = self.get_video_source_from_page()
        if page_video_src:
            if '.m3u8' in page_video_src:
                return page_video_src, None
            elif '.mp4' in page_video_src:
                return None, page_video_src
        
        # 如果页面元素没有找到，再使用性能日志
        for attempt in range(max_attempts):
            time.sleep(2)
            try:
                performance_log = self.driver.get_log('performance')
                for packet in performance_log[::-1]:
                    message = json.loads(packet.get('message')).get('message')
                    if message.get('method') != 'Network.responseReceived':
                        continue
                        
                    url = message.get('params', {}).get('response', {}).get('url', '')
                    if url:
                        # 过滤掉统计和心跳监控链接
                        if any(filter_keyword in url for filter_keyword in [
                            'webtrn.cn/page?sid=',  # 统计链接
                            'heartBeat',            # 心跳监控
                            'evt=',                 # 事件统计
                            'analytics',            # 分析统计
                            'track',               # 追踪统计
                        ]):
                            continue
                            
                        # 只匹配真正的视频文件
                        if '.m3u8' in url and not any(filter_keyword in url for filter_keyword in ['page?', 'sid=']):
                            m3u8_url = url
                            print(f"发现m3u8视频链接: {url}")
                            break
                        elif '.mp4' in url and not any(filter_keyword in url for filter_keyword in ['page?', 'sid=', 'webtrn.cn']):
                            # 确保是直接的mp4文件链接，不是统计链接
                            if url.endswith('.mp4') or 'video' in url.lower():
                                mp4_url = url
                                print(f"发现mp4视频链接: {url}")
                                break
                
                if m3u8_url or mp4_url:
                    break
                    
            except Exception as e:
                print(f"抓取日志异常: {e}")
        
        return m3u8_url, mp4_url

    def download_video(self, video_url, filename, video_type='auto'):
        """下载视频文件"""
        if video_type == 'auto':
            if '.m3u8' in video_url:
                video_type = 'm3u8'
            elif '.mp4' in video_url:
                video_type = 'mp4'
            else:
                print(f"未知视频格式: {video_url}")
                return False
        
        if video_type == 'm3u8':
            return self.download_m3u8_video(video_url, filename)
        elif video_type == 'mp4':
            return self.download_mp4_video(video_url, filename)
        else:
            print(f"不支持的视频格式: {video_type}")
            return False

    def load_video_item(self, learn_item_id, max_retries=3):
        """调用openLearnResItem函数加载视频"""
        for attempt in range(max_retries):
            try:
                print(f"尝试加载视频 (第{attempt+1}次)...")
                
                # 详细检查和调用
                result = self.driver.execute_script(f"""
                    try {{
                        // 详细检查环境
                        if (typeof openLearnResItem !== 'function') {{
                            return 'openLearnResItem函数不存在';
                        }}
                        
                        // 检查必要的全局变量
                        if (typeof window.$ === 'undefined') {{
                            return 'jQuery($)未加载';
                        }}
                        
                        // 检查学习项目ID是否有效
                        if (!'{learn_item_id}' || '{learn_item_id}' === '') {{
                            return '学习项目ID无效';
                        }}
                        
                        // 等待一小段时间确保页面完全准备
                        setTimeout(function() {{
                            try {{
                                openLearnResItem('{learn_item_id}', 'video');
                            }} catch(err) {{
                                console.error('openLearnResItem调用异常:', err);
                            }}
                        }}, 500);
                        
                        return 'success';
                    }} catch(e) {{
                        return 'error: ' + e.message + ' (行号: ' + (e.lineNumber || '未知') + ')';
                    }}
                """)
                
                if result == 'success':
                    print(f"✓ 视频加载请求已发送")
                    return True
                else:
                    print(f"✗ 第{attempt+1}次尝试失败: {result}")
                    if attempt < max_retries - 1:
                        print("等待3秒后重试...")
                        time.sleep(3)
                        
            except Exception as e:
                print(f"✗ 第{attempt+1}次JS执行异常: {e}")
                if attempt < max_retries - 1:
                    time.sleep(2)
        
        return False 